var mongodb = require('mongodb');
var redis   = require('redis');
var http    = require('http');
var https   = require('https');
var util    = require('util');
var sys     = require('sys');
var fs      = require('fs');
var url     = require('url');
var qs      = require('querystring');
var zlib    = require('zlib');

var common  = require('./common.js');
var csv     = require('./csv.js');
var config  = require(fs.existsSync('../config.js') ? '../config.js' : './config.js');

function loadGlobalServerConf() {
    global.gConfGlobalServer = new csv.GlobalCSV('conf/globalserver.dat');
    gConfGlobalServer.ServerStartTime = csv.parseDate(gConfGlobalServer.ServerStartTime);
    gConfGlobalServer.FirstLeagueWarTime = csv.parseDate(gConfGlobalServer.FirstLeagueWarTime);
    gConfGlobalServer.SystemRewardTime = csv.parseDate(gConfGlobalServer.SystemRewardTime);
    gConfGlobalServer.FirstServerWarTime = csv.parseDate(gConfGlobalServer.FirstServerWarTime);
    gConfGlobalServer.FirstBattleWorldTime = csv.parseDate(gConfGlobalServer.FirstBattleWorldTime);
    gConfGlobalServer.FirstChampsBattleTime = csv.parseDate(gConfGlobalServer.FirstChampsBattleTime);
}

function checkBattleMonsterConf(conf, desc) {
    if (!gConfMonster[conf.Boss]) {
        ERROR(util.format('%s boss monster %d invalid', desc, conf.Boss));
    }

    for (var pos = 0; pos <= 8; ++pos) {
        var monsterId = conf['Pos'+pos];
        if (monsterId && !gConfMonster[monsterId]) {
            ERROR(util.format('%s Pos%d monster %d invalid', desc, pos, monsterId));
        }
    }
}

function loadConf() {
    if (!global.gConfGlobalServer) {
        loadGlobalServerConf();
    }

    global.gConfGlobal = new csv.GlobalCSV('conf/global.dat');
    gConfGlobal.PayCarnivalOpenTime = gConfGlobalServer.ServerStartTime + gConfGlobal.PayCarnivalOpenDays*86400;
    gConfGlobal.PetOpenRelativeTime = csv.parseDate(gConfGlobal.PetOpenRelativeTime);
    gConfGlobal.DailyPayEndTime = csv.parseDate(gConfGlobal.DailyPayEndTime);
    gConfGlobal.SmashLandPassAwardTime = csv.parseDate(gConfGlobal.SmashLandPassAwardTime);
    gConfGlobal.ChampsBattleFirstOpenTime = csv.parseDate(gConfGlobal.ChampsBattleFirstOpenTime);
    gConfGlobal.BattleWorldFirstOpenTime = csv.parseDate(gConfGlobal.BattleWorldFirstOpenTime);

    global.gConfSwitch = new csv.SwitchCSV('conf/switch.dat');

    global.gConfLevel = new csv.CommonCSV('conf/level.dat', ['Level']);
    global.gConfTavern = new csv.CommonCSV('conf/tavern.dat', ['Type','CashTimes']);
    
    global.gConfRole = new csv.RoleCSV('conf/role.dat', ['Id']);
    global.gConfRoleLevel = new csv.CommonCSV('conf/rolelevel.dat',['Level']);
    global.gConfRoleLevelMax = 0;
    for (var level in gConfRoleLevel) {
        if (+level > gConfRoleLevelMax) {
            gConfRoleLevelMax = +level;
        }
    }

    global.gConfSoldier = new csv.CommonCSV('conf/soldier.dat', ['Soldier','Level']);
    global.gConfGrouth = new csv.CommonCSV('conf/grouth.dat', ['Quantity']);
    global.gConfSkill = new csv.CommonCSV('conf/skill.dat', ['Soldier','Skill']);
    global.gConfEquip = new csv.CommonCSV('conf/equip.dat', ['Level']);
    global.gConfStrengthen = new csv.CommonCSV('conf/strengthen.dat', ['Strength']);
    global.gConfWeapon = new csv.CommonCSV('conf/weapon.dat', ['Strength']);
    global.gConfArmor = new csv.CommonCSV('conf/armor.dat', ['Strength']);
    global.gConfAccessory = new csv.CommonCSV('conf/accessory.dat', ['Strength']);
    global.gConfSkillEffect = new csv.CommonCSV('conf/skilleffect.dat',
                                                 ['Soldier','Skill','Level']);
    global.gConfMonster = new csv.CommonCSV('conf/monster.dat',['Id']);
    global.gConfBattle  = new csv.PVECSV('conf/battle.dat',['Id']);
    global.gConfLeagueBoss = new csv.PVECSV('conf/leagueboss.dat',['Level']);
    global.gConfWorldBoss = new csv.PVECSV('conf/worldboss.dat', ['Id']);

    global.gConfTower = new csv.TOWERCSV('conf/tower.dat',['Tower', 'Id']);
    for (var tower in gConfTower) {
        var towerConf = gConfTower[tower];
        for (var id in towerConf) {
            checkBattleMonsterConf(towerConf[id], util.format('tower.dat Tower=%d Id=%d', tower, id));
        }
    }

    global.gConfKillGeneral = new csv.CommonCSV('conf/killgeneral.dat',['Id']);
    global.gConfMaterial = new csv.CommonCSV('conf/material.dat', ['Id']);
    for( var id in gConfMaterial ) {
        var material = gConfMaterial[id];
        if( material.EndTime ) {
            material.EndTime = csv.parseDate(material.EndTime);
        }
    }

    global.gConfGem = new csv.CommonCSV('conf/gem.dat', ['Id']);
    
    global.gConfTavern = new csv.TavernCSV('conf/tavern.dat', ['Level']);
    global.gConfTraining = new csv.TavernCSV('conf/training.dat', ['Id']);
    global.gConfBusiness = new csv.BusinessCSV('conf/business.dat', ['Id']);
    global.gConfTech = new csv.CommonCSV('conf/tech.dat', ['Id']);
    global.gConfShop = new csv.CommonCSV('conf/shop.dat', ['Id']);
    global.gConfSoldierInit = new csv.CommonCSV('conf/soldierinit.dat', ['Soldier']);

    global.gConfRank = new csv.CommonCSV('conf/rank.dat', ['Id']);
    global.gConfMine = new csv.CommonCSV('conf/mine.dat', ['Quantity']);
    global.gConfMineDistribute = new csv.CommonCSV('conf/minedistribute.dat', ['Level']);

    global.gConfDailyTask = new csv.DailyTaskCSV('conf/dailytask.dat', ['Id']);
    global.gConfTaskReward = new csv.CommonCSV('conf/taskreward.dat', ['Score']);

    global.gConfOnlineReward = new csv.CommonCSV('conf/onlinereward.dat', ['Time']);
    global.gConfBuy = new csv.CommonCSV('conf/buy.dat', ['Times']);
    global.gConfLevelPack = new csv.CommonCSV('conf/levelpack.dat',['Level']);
    global.gConfTask = new csv.CommonCSV('conf/task.dat',['Id']);
    
    global.gConfSign = new csv.CommonCSV('conf/sign.dat',['Id']);
    global.gConfLogin = new csv.CommonCSV('conf/login.dat',['Id']);

    global.gConfSystemReward = new csv.CommonCSV('conf/systemreward.dat',['Id']);
    global.gConfSoul = new csv.CommonCSV('conf/soul.dat',['Level']);

    global.gConfLeagueLevel = new csv.CommonCSV('conf/leaguelevel.dat',['Level']);
    global.gConfLeagueTech = new csv.CommonCSV('conf/leaguetech.dat',['Id','Level']);

    global.gConfLeagueReward = new csv.CommonCSV('conf/leaguereward.dat',['Id']);
    global.gConfLeagueBossReward = new csv.CommonCSV('conf/leaguebossreward.dat', ['Id']);

    global.gConfVip = new csv.CommonCSV('conf/vip.dat',['Level']);

    global.gConfSmashLand = new csv.SmashLandCSV('conf/smashland.dat', ['Id', 'Level']);
    global.gConfSmashLandTeam = new csv.SmashLandTeamCSV('conf/smashland_team.dat', ['Id']);
    global.gConfSmashLandBuff = new csv.CommonCSV('conf/smashland_buff.dat', ['Id']);
    global.gConfSmashLandShop = new csv.CommonCSV('conf/smashlandshop.dat', ['Id']);
    global.gConfSmashLandRankAward = new csv.CommonCSV('conf/smashland_rank_award.dat', ['Id']);
    for (var id in gConfSmashLandTeam) {
        checkBattleMonsterConf(gConfSmashLandTeam[id], util.format('smashland_team.dat Id=%d', id));
    }
    
    // 活动配置
    global.gConfActivities = new csv.ActivityCSV('conf/activities.dat',['Key']);
    global.gConfActivitySchedule = new csv.CommonCSV('conf/activities_schedule.dat',['Id']);
    global.gConfActivityCondition = new csv.CommonCSV('conf/activities_condition.dat',['Key', 'ConfId']);
    for (var activity in gConfActivityCondition) {
        var conditions = gConfActivityCondition[activity];
        for (var id in conditions) {
            conditions[id].StartServerTime = csv.parseDate(conditions[id].StartServerTime);
            conditions[id].EndServerTime = csv.parseDate(conditions[id].EndServerTime);
        }
    }

    for (var key in gConfActivities) {
        var activity = gConfActivities[key];
        var now = common.getTime();

        activity.OpenDay = activity.OpenDay || 0;
        activity.DelayDays = activity.DelayDays || 0;
        activity.IsSchedule = false;
        for (var id in gConfActivitySchedule) {
            if (gConfActivitySchedule[id].Key == key) {
                activity.IsSchedule = true;
            }
        }
        
        var conditions = gConfActivityCondition[key];
        if (conditions) {
            for (var id in conditions) {
                var condition = conditions[id];
                if (condition.StartServerTime <= gConfGlobalServer.ServerStartTime 
                && condition.EndServerTime >= gConfGlobalServer.ServerStartTime) {
                    activity.ConfId = id;
                    break;
                }
            }
        }

        if (gConfGlobalServer.ServerStartTime < activity.OpenTime) {
            delete gConfActivities[key];
            continue;
        }

        // 活动无效
        if (!activity.StartTime || !activity.EndTime || activity.StartTime >= activity.EndTime) {
            if (!activity.IsSchedule) {
                delete gConfActivities[key];
                continue;
            }
        } else {
            if (activity.IsSchedule) {
                var endDay = 0;
                for (var id in gConfActivitySchedule) {
                    var schedule = gConfActivitySchedule[id];
                    if (schedule.Key != key) continue;
                    
                    if (schedule.EndDay > endDay) {
                        endDay = schedule.EndDay;
                    }
                }

                if (activity.OpenDay <= endDay) {
                    ERROR(util.format('activities:%s OpenDay=%s schedule.EndDay=%s', key, activity.OpenDay, endDay));
                    activity.IsSchedule = false;
                }
            }
        }
    }

    // 奖励配置
    global.gConfAvSeven = new csv.CommonCSV('conf/avseven.dat',['Day']);
    global.gConfAvLevelTop = new csv.CommonCSV('conf/avleveltop.dat',['Level']);
    global.gConfAvLuckyWheel = new csv.CommonCSV('conf/avluckywheel.dat',['ConfId','Star']);
    global.gConfAvInvest = new csv.CommonCSV('conf/avinvest.dat',['Id', 'RewardId']);
    global.gConfAvLimitBuy = new csv.CommonCSV('conf/avlimitbuy.dat',['Id']);
    global.gConfAvSurprise = new csv.CommonCSV('conf/avsurprise.dat', ['ConfId','Grid']);
    global.gConfAvCrazyRank = new csv.CommonCSV('conf/avcrazyrank.dat', ['Rank']);
    global.gConfAvCrazySend = new csv.AvCrazySendCSV('conf/avcrazysend.dat', ['DebrisNum']);
    global.gConfAvFeed = new csv.CommonCSV('conf/avfeed.dat', ['Id']);
    global.gConfAvYellowDiamond = new csv.CommonCSV('conf/avyellowdiamond.dat', ['Id']);
    global.gConfAvCharge = new csv.CommonCSV('conf/avcharge.dat',['ConfId','Id']);
    global.gConfAvWish = new csv.CommonCSV('conf/avwish.dat', ['Id']);
    global.gConfAvYellowCharge = new csv.CommonCSV('conf/avyellowcharge.dat',['Id']);
    global.gConfAvTower = new csv.CommonCSV('conf/avtower.dat',['Floor']);
    global.gConfAvTowerRank = new csv.CommonCSV('conf/avtowerrank.dat',['Rank']);
    global.gConfAvFightForce = new csv.CommonCSV('conf/avfightforce.dat',['FightForce']);
    global.gConfAvFightForceRank = new csv.CommonCSV('conf/avfightforcerank.dat',['Rank']);
    global.gConfAvPlayerLevel = new csv.CommonCSV('conf/avplayerlevel.dat',['Level']);
    global.gConfAvLevelRank = new csv.CommonCSV('conf/avlevelrank.dat',['Rank']);
    global.gConfAvGroupOn = new csv.CommonCSV('conf/avgroupon.dat',['Day']);
    global.gConfAvWestern = new csv.AvWesternCSV('conf/avwestern.dat',['Id']);
    global.gConfAvWealth = new csv.CommonCSV('conf/avwealth.dat',['Id']);
    global.gConfAvGemBuy = new csv.CommonCSV('conf/avgembuy.dat',['ConfId','Id']);
    global.gConfAvYellowDiamondRole = new csv.CommonCSV('conf/avyellowdiamondrole.dat',['Id']);
    global.gConfAvCostGift = new csv.CommonCSV('conf/avcostgift.dat',['ConfId', 'Id']);
    global.gConfAvThanksBack = new csv.CommonCSV('conf/avthanksback.dat',['ConfId', 'Id']);
    global.gConfAvChargeFeedSlot = new csv.CommonCSV('conf/avchargefeed_slot.dat',['ConfId', 'Id']);
    global.gConfAvChargeFeedScore = new csv.CommonCSV('conf/avchargefeed_score.dat',['ConfId', 'Id']);
    global.gConfAvNewCharge = new csv.CommonCSV('conf/avnewcharge.dat',['ConfId','Id']);
    global.gConfAvMyLimit = new csv.CommonCSV('conf/avmylimit.dat',['ConfId', 'Id']);
    global.gConfAvRoleSend = new csv.CommonCSV('conf/avrolesend.dat',['ConfId', 'Id']);
    global.gConfAvPetGift = new csv.CommonCSV('conf/avpetgift.dat',['ConfId', 'Level']);
    global.gConfAvBreakEgg = new csv.CommonCSV('conf/avbreakegg.dat',['ConfId', 'Id']);
    global.gConfAvChargeRole = new csv.CommonCSV('conf/avchargerole.dat',['Cash']);
    global.gConfAvChargeLimit = new csv.CommonCSV('conf/avchargelimit.dat',['ConfId', 'Cash']);
    global.gConfAvChargeGodLimit = new csv.CommonCSV('conf/avchargegod_limit.dat',['ConfId', 'Cash']);
    global.gConfAvChargeGodReward = new csv.CommonCSV('conf/avchargegod_reward.dat',['ConfId', 'Cash']);
    global.gConfAvStarGift = new csv.CommonCSV('conf/avstargift.dat',['Id']);
    
    global.gConfAvPay = new csv.CommonCSV('conf/avpay.dat',['ConfId', 'Day','Pay']);
    global.gConfAvPayRank = new csv.CommonCSV('conf/avpayrank.dat',['ConfId', 'Id']);
    for (var confId in gConfAvPayRank) {
        var confs = gConfAvPayRank[confId];
        confs.CashMin = confs[5].PayMin;
    }

    global.gConfAvDailyPayRank = new csv.CommonCSV('conf/avdailypayrank.dat',['ConfId', 'Day', 'Id']);
    for (var confId in gConfAvDailyPayRank) {
        var confs = gConfAvDailyPayRank[confId];
        var dayConfs = confs[1];
        for (var id in dayConfs) {
            if (!confs.CashMin || dayConfs[id].PayMin < confs.CashMin) {
                confs.CashMin = dayConfs[id].PayMin;
            }
        }
    }

    global.gConfAvDiamondCard = new csv.CommonCSV('conf/avdiamondcard.dat',['Id']);
    global.gConfAvDiamondCardAward = new csv.CommonCSV('conf/avdiamondcard_award.dat',['Id']);
    global.gConfAvDiamondCardCost = new csv.CommonCSV('conf/avdiamondcard_cost.dat',['Id']);
    global.gConfAvDiamondCardItem = new csv.CommonCSV('conf/avdiamondcard_item.dat',['Id']);
    for( var id in gConfAvDiamondCard ) {
        var items = gConfAvDiamondCard[id].Item.split("|");
        var itemWeights = {};
        items.forEach(function(item){
            itemWeights[item] = gConfAvDiamondCardItem[item].Weight;
        });
        gConfAvDiamondCard[id].Item = itemWeights;
    }

    global.gConfAvServerPayRank = new csv.CommonCSV('conf/avserverpayrank.dat',['Id']);
    global.gConfAvMysticShop = new csv.CommonCSV('conf/avmysticshop.dat',['Id']);
    global.gConfAvMysticShopCost = new csv.CommonCSV('conf/avmysticshop_cost.dat',['Id', 'Buy']);
    global.gConfAvRichSend = new csv.CommonCSV('conf/avrichsend.dat',['Cash']);
    global.gConfAvRichSendRank = new csv.CommonCSV('conf/avrichsendrank.dat',['Id']);


    //----------计算各种PayRank进榜条件
    gConfGlobal.ServerPayRankCashMin = gConfAvServerPayRank[5].PayMin;
    gConfGlobal.RichSendRankCashMin = gConfAvRichSendRank[5].PayMin;
    //----------结束计算各种PayRank进榜条件

    global.gConfCombine = new csv.CombineCSV('conf/combine.dat',['Id']);
    for (var id in gConfCombine) {
        var combine = gConfCombine[id];
        if (combine.Tother) continue;

        for (var otherId in gConfCombine) {
            var otherCombine = gConfCombine[otherId];
            if (combine.Color == otherCombine.Color && combine.Side != otherCombine.Side) {
                combine.Tother = otherId;
                otherCombine.Tother = id;
                break;
            }
        }
    }

    global.gConfGloryShop = new csv.CommonCSV('conf/gloryshop.dat',['Id']);

    global.gConfGradeLevel = new csv.CommonCSV('conf/gradelevel.dat',['Level']);
    global.gConfLeagueWarCity = new csv.CommonCSV('conf/leaguewarcity.dat',['Id']);
    global.gConfLeagueWarRank = new csv.CommonCSV('conf/leaguewarrank.dat',['Rank']);

    global.gConfLeagueDuplicate = new csv.PVECSV('conf/leagueduplicate.dat',['Id']);
    global.gConfAvLeagueDuplicate = new csv.CommonCSV('conf/leagueduplicatereward.dat',['Chapter', 'Type']);
    for (var id in gConfLeagueDuplicate) {
        var totalHP = 0;
        var totalMonster = 0;
        var duplicateConf = gConfLeagueDuplicate[id];
        for (var pos = 0; pos < 9; ++pos) {
            var monsterId = duplicateConf['Pos'+pos];
            if (monsterId) {
                var monsterConf = gConfMonster[monsterId];
                if (monsterConf) {
                    totalHP += monsterConf.Health;
                    totalMonster += 1;
                } else {
                    ERROR(util.format("leagueduplicate.dat id:%d pos:%d monster invalid", id, pos));
                }
            }
        }
        duplicateConf.TotalHP = totalHP;
        duplicateConf.TotalMonster = totalMonster;

        if (!totalHP || !totalMonster || totalHP <= 0 || totalMonster <= 0) {
            ERROR(util.format("leagueduplicate.dat id:%d totalHP:%d totalMonster:%d", 
                id, totalHP, totalMonster));
        }
    }
    global.gConfBlackShop = new csv.CommonCSV('conf/blackshop.dat',['Id']);
    global.gConfBox = new csv.CommonCSV('conf/box.dat', ['Id']);

    global.gConfSlot = new csv.CommonCSV('conf/slot.dat',['Id', 'Index']);

    global.gConfTomb = new csv.PVECSV('conf/tomb.dat', ['Id']);
    global.gConfTombReward = new csv.CommonCSV('conf/tombreward.dat', ['Id', 'Pos']);

    global.gConfCard = new csv.CommonCSV('conf/card.dat', ['Id']);

    global.gConfAchieveLevel = new csv.CommonCSV('conf/achieve_level.dat', ['Level']);
    global.gConfAchieveGoal = new csv.CommonCSV('conf/achieve_goal.dat', ['Id', 'GoalLevel']);

    global.gConfServerWarSchedule = new csv.CommonCSV('conf/serverwarschedule.dat', ['Progress']);
    global.gConfServerWarReward = new csv.CommonCSV('conf/serverwarreward.dat', ['Rank']);
    global.gConfServerWarSupport = new csv.CommonCSV('conf/serverwarsupport.dat', ['Rank']);

    global.gConfWorldBossReward = new csv.CommonCSV('conf/worldbossreward.dat', ['Week', 'Rank']);

    global.gConfDayWheel = new csv.CommonCSV('conf/daywheel.dat', ['Day']);
    global.gConfDayWheelReward = new csv.CommonCSV('conf/daywheelreward.dat', ['Id']);

    global.gConfHitBoxReward = new csv.CommonCSV('conf/hitboxreward.dat', ['Id']);
    global.gConfPet = new csv.CommonCSV('conf/pet.dat', ['Level']);
    global.gConfPetSkillEffect = new csv.CommonCSV('conf/petskilleffect.dat', ['Skill', 'Level']);

    global.gConfCloud = new csv.CommonCSV('conf/cloud.dat', ['Id']);
    global.gConfCloudLevel = new csv.CommonCSV('conf/cloudlevel.dat', ['Level']);
    global.gConfCloudShop = new csv.CloudShopCSV('conf/cloudshop.dat', ['Id']);
    global.gConfCloudLottery = new csv.CommonCSV('conf/cloudlottery.dat', ['Pos']);

    global.gConfGrouthBreak = new csv.CommonCSV('conf/grouthbreak.dat', ['Level']);
    global.gConfSoulBreak = new csv.CommonCSV('conf/soulbreak.dat', ['Level']);
    global.gConfGodLevel = new csv.CommonCSV('conf/godlevel.dat', ['Level']);
    global.gConfRoleStar = new csv.CommonCSV('conf/rolestar.dat', ['Soldier', 'Level']);
    global.gConfRoleStarSpecialEffect = new csv.CommonCSV('conf/rolestarspecialeffect.dat', ['Soldier', 'Id']);
    global.gConfHoroscopeGrid = new csv.CommonCSV('conf/horoscope_grid.dat', ['Id', 'GridId']);
    global.gConfHoroscopeGridPos = new csv.CommonCSV('conf/horoscope_grid.dat', ['Id', 'PosX', 'PosY']);
    global.gConfHoroscopeEffect = new csv.CommonCSV('conf/horoscope_effect.dat', ['Id']);

    global.gConfBattleWorldSchedule = new csv.CommonCSV('conf/battleworldschedule.dat', ['Progress']);
    global.gConfBattleWorldReward = new csv.CommonCSV('conf/battleworldreward.dat', ['Rank']);
    global.gConfBattleWorldSupport = new csv.CommonCSV('conf/battleworldsupport.dat', ['Rank']);
    global.gConfBattleWorldFieldCity = new csv.CommonCSV('conf/battleworldfieldcity.dat', ['Id']);

    global.gConfDailyPay = new csv.CommonCSV('conf/dailypay.dat', ['Id']);
    global.gConfAvPayCarnival = new csv.CommonCSV('conf/avpaycarnival.dat', ['Id']);
    global.gConfAvPayCarnivalCost = new csv.CommonCSV('conf/avpaycarnivalcost.dat', ['Id']);

    global.gConfHuaTuoCost = new csv.CommonCSV('conf/huatuo_cost.dat', ['Count']);
    global.gConfHuaTuoLevel = new csv.CommonCSV('conf/huatuo_level.dat', ['Level']);
    global.gConfHuaTuoPellet = new csv.CommonCSV('conf/huatuo_pellet.dat', ['Id', 'Quantity']);
    global.gConfHuaTuoQuantity = new csv.CommonCSV('conf/huatuo_quantity.dat', ['Quantity']);
    global.gConfHuaTuoScore = new csv.CommonCSV('conf/huatuo_score.dat', ['Id']);

    global.gConfTroopMatchRank = new csv.CommonCSV('conf/troopmatch_rank.dat', ['Rank']);
    global.gConfTroopMatchRole = new csv.CommonCSV('conf/troopmatch_role.dat', ['Id']);
    global.gConfTroopMatchScore = new csv.CommonCSV('conf/troopmatch_score.dat', ['Win']);
    global.gConfTroopMatchShop = new csv.CommonCSV('conf/troopmatch_shop.dat', ['Id']);
    global.gConfTroopMatchWinStreak = new csv.CommonCSV('conf/troopmatch_win_streak.dat', ['Win']);

    global.gConfEquipStar = new csv.CommonCSV('conf/equipstar.dat', ['Star']);

    global.gConfAvNewYearFirstPay = new csv.CommonCSV('conf/avnewyearfirstpay.dat', ['Day']);

    global.gConfServerMine = new csv.CommonCSV('conf/servermine.dat', ['Quantity']);

    global.gConfInviteGoal = new csv.CommonCSV('conf/invite_goal.dat', ['Id']);
    global.gConfInviteReward = new csv.CommonCSV('conf/invite_reward.dat', ['Id']);

    global.gConfAvLuckyNumber = new csv.CommonCSV('conf/avluckynumber.dat', ['Day']);
    global.gConfAvRedPacket = new csv.CommonCSV('conf/avredpacket.dat', ['Cash']);

    global.gConfYearBossReward = new csv.CommonCSV('conf/yearbossreward.dat', ['Rank']);
    global.gConfYearBoss = new csv.PVECSV('conf/yearboss.dat', ['Id']);

    global.gConfAvNewRedPacket = new csv.CommonCSV('conf/avnewredpacket.dat', ['Cash']);

    global.gConfAvSuperCard = new csv.CommonCSV('conf/avsupercard.dat',['ConfId', 'Id']);
    global.gConfAvSuperCardCost = new csv.CommonCSV('conf/avsupercard_cost.dat',['Id']);
    global.gConfAvSuperCardItem = new csv.CommonCSV('conf/avsupercard_item.dat',['ConfId', 'Id']);
    for (var confId in gConfAvSuperCard) {
        var confAvSuperCard = gConfAvSuperCard[confId];
        var confAvSuperCardItem = gConfAvSuperCardItem[confId];
        for (var id in confAvSuperCard) {
            var items = confAvSuperCard[id].Item.split("|");
            var itemWeights = {};
            items.forEach(function(item){
                itemWeights[item] = confAvSuperCardItem[item].Weight;
            });
            confAvSuperCard[id].Item = itemWeights;
            
            var mark = confAvSuperCard[id].Mark;
            if (mark) {
                var Special = {};
                for (var item in confAvSuperCardItem) {
                    var itemObj = confAvSuperCardItem[item];
                    if (itemObj.Mark == mark) {
                        Special[item] = itemObj.Weight;
                    }
                }
                confAvSuperCard[id].Special = Special;
            }
        }
    }

    global.gConfAvLoginInvest = new csv.CommonCSV('conf/avlogininvest.dat',['Cash']);
    global.gConfAvLevelInvest = new csv.CommonCSV('conf/avlevelinvest.dat',['Cash']);

    global.gConfDragonWish = new csv.CommonCSV('conf/dragonwish.dat',['Id']);

    global.gConfAvNewFirstPay = new csv.CommonCSV('conf/avnewfirstpay.dat',['Cash']);
    global.gConfAvNewForgeLevel = new csv.CommonCSV('conf/avnewforgelevel.dat',['Id']);

    global.gConfAvLeagueKing = new csv.CommonCSV('conf/avleagueking.dat',['Star']);

    global.gConfAvDigTreasure = new csv.CommonCSV('conf/avdigtreasure.dat',['Id']);
    global.gConfAvDigTreasureAxe = new csv.CommonCSV('conf/avdigtreasureaxe.dat',['Depth']);
    global.gConfAvDigTreasureThief = new csv.PVECSV('conf/avdigtreasurethief.dat',['Id']);

    global.gConfHorse = new csv.CommonCSV('conf/horse.dat',['Id']);
    global.gConfHarness = new csv.CommonCSV('conf/harness.dat',['Id']);
    global.gConfHarnessLevel = new csv.CommonCSV('conf/harnesslevel.dat',['Level']);
    global.gConfHorseLevel = new csv.CommonCSV('conf/horselevel.dat',['Level']);
    global.gConfHorseSell = new csv.CommonCSV('conf/horsesell.dat',['Level']);

    global.gConfAvPetCost = new csv.CommonCSV('conf/avpetcost.dat',['ConfId','Level']);

    global.gConfAvVipBox = new csv.CommonCSV('conf/avvipbox.dat',['Id']);

    global.gConfMyBattle = new csv.PVECSV('conf/mybattle.dat',['Id']);

    global.gConfEquipRefine = new csv.CommonCSV('conf/equiprefine.dat',['Level']);

    global.gConfLotteryShop = new csv.CommonCSV('conf/lotteryshop.dat',['Id']);

    global.gConfWing = new csv.CommonCSV('conf/wing.dat',['Level']);

    global.gConfBlessDesc = new csv.CommonCSV('conf/blessdesc.dat', ['Num']);
    global.gConfBlessDice = new csv.CommonCSV('conf/blessdice.dat',['Id']);
    global.gConfBlessShop = new csv.CommonCSV('conf/blessshop.dat',['Id']);

    global.gConfAvAllGift = new csv.CommonCSV('conf/avallgift.dat',['ConfId','Day','Type']);

    global.gConfAvLuckyCircle = new csv.CommonCSV('conf/avluckycircle.dat',['Id']);
    global.gConfAvLuckyCircleAward = new csv.CommonCSV('conf/avluckycircle_award.dat',['Id']);
    global.gConfAvLuckyCircleCost = new csv.CommonCSV('conf/avluckycircle_cost.dat',['Id']);
    global.gConfAvLuckyCircleItem = new csv.CommonCSV('conf/avluckycircle_item.dat',['Id']);
    global.gConfAvLuckyCircleScore = new csv.CommonCSV('conf/avluckycircle_score.dat',['Id']);
    
    global.gConfAvNationalSevenAward = new csv.CommonCSV('conf/avnationalseven_reward.dat', ['Day']);

    for( var id in gConfAvLuckyCircle ) {
        var items = gConfAvLuckyCircle[id].Item.split("|");
        var itemWeights = {};
        items.forEach(function(item){
            itemWeights[item] = gConfAvLuckyCircleItem[item].Weight;
        });
        gConfAvLuckyCircle[id].Item = itemWeights;
    }

    global.gConfAvAllCharge = new csv.CommonCSV('conf/avallcharge.dat',['Id']);
    global.gConfAvYearFeedBack = new csv.CommonCSV('conf/avyearfeedback.dat',['Id']);
    
    global.gConfAvReturnLevelup = new csv.CommonCSV('conf/avreturnlevelup.dat', ['ConfId', 'LeaveDays']);
    for (id in gConfAvReturnLevelup) {
        var maxLeaveDays = 0;
        var confs = gConfAvReturnLevelup[id];
        for (var days in confs) {
            if ((+days) > maxLeaveDays) {
                maxLeaveDays = (+days);
            }
        }
        confs.MaxLeaveDays = maxLeaveDays;
    }

    // 新服红包配置
    global.gConfAvNewServerGift = new csv.CommonCSV('conf/avnewservergift.dat', ['ConfId']);

    // 觉醒福利配置
    global.gConfAvGodGiftCount = new csv.CommonCSV('conf/avgodgifttopreward.dat', ['ConfId', 'Num']);
    global.gConfAvGodGift = new csv.CommonCSV('conf/avgodgiftreward.dat', ['ConfId']);


    // 充值幸运转配置
    global.gConfAvLuckyCharge = new csv.CommonCSV('conf/avluckycharge.dat',['ConfId', 'Pos']);
    global.gConfAvLuckyChargeItem = new csv.CommonCSV('conf/avluckycharge_item.dat',['ConfId', 'Id']);
    global.gConfAvLuckyChargeCost = new csv.CommonCSV('conf/avluckycharge_cost.dat',['Times']);
    global.gConfAvLuckyChargeRank = new csv.CommonCSV('conf/avluckycharge_rank.dat',['ConfId', 'Id']);

    global.gConfAvWorshipSaintDaily = new csv.CommonCSV('conf/avworshipsaintdaily.dat', ['Day']);
    global.gConfAvWorshipSaintLevel = new csv.CommonCSV('conf/avworshipsaintlevel.dat', ['Level']);

    global.gConfPrisonAward = new csv.CommonCSV('conf/prison_award.dat', ['Id']);

    global.gConfImperialExaminationAward = new csv.CommonCSV('conf/imperialexamination_award.dat', ['Id']);
    global.gConfImperialExaminationExchange = new csv.CommonCSV('conf/imperialexamination_exchange.dat', ['Id']);
    global.gConfImperialExaminationQA = new csv.CommonCSV('conf/imperialexamination_QA.dat', ['Id']);

    global.gConfShotMeArrowCost = new csv.CommonCSV('conf/shotmearrow_cost.dat', ['ConfId', 'Times']);
    global.gConfShotMeArrowShop = new csv.CommonCSV('conf/shotmearrow_shop.dat', ['Id']);
    global.gConfShotMeArrowReward = new csv.CommonCSV('conf/shotmearrow_reward.dat', ['ConfId', 'Id']);
    global.gConfShotMeArrowRankAward = new csv.CommonCSV('conf/shotmearrow_rank_award.dat', ['ConfId', 'Id']);
    
    global.gConfQQTask = {};
    if (gConfSwitch.QQTask) {
        global.gConfQQTask = new csv.CommonCSV('conf/qqtask.dat', ['Id', 'Step']);
    }
    
    //王者战场相关配置
    global.gConfChampsBattleSchedule = new csv.CommonCSV('conf/champsbattle_schedule.dat', ['Step']);
    global.gConfChampsBattleField = new csv.CommonCSV('conf/champsbattle_field.dat', ['Id']);
    global.gConfChampsBattleFieldCity = new csv.CommonCSV('conf/champsbattle_fieldcity.dat', ['Id']);
    global.gConfChampsBattleCityLevel = new csv.CommonCSV('conf/champsbattle_citylevel.dat', ['Level']);
    global.gConfChampsBattleRelive = new csv.CommonCSV('conf/champsbattle_relive.dat', ['Time']);
	global.gConfChampsBattleTeam = new csv.MonsterTeamCSV('conf/champsbattle_team.dat', ['Id']);
    objectForEach(gConfChampsBattleTeam, function(id, team) {
        checkBattleMonsterConf(team, util.format('conf/champsbattle_team.dat Id=%d', id));
    });
	global.gConfChampsBattleReward = new csv.CommonCSV('conf/champsbattle_reward.dat', ['Type', 'Step', 'Win']);

    //新好友相关配置
    global.gConfFriendMaChaoBox = new csv.CommonCSV('conf/friend_machao_box.dat', ['Id']);
    global.gConfFriendPointAwards = new csv.CommonCSV('conf/friend_point_awards.dat', ['Id']);

    global.gConfEdlerSignStar = new csv.CommonCSV('conf/elder_sign_star.dat', ['Id']);
    global.gConfEdlerSignAssistorAwards = new csv.CommonCSV('conf/elder_sign_awards_assistor.dat', ['Id']);
    global.gConfEdlerSignOwnerAwards = new csv.CommonCSV('conf/elder_sign_awards_owner.dat', ['Id']);

    global.gConfInsurgencyTeam = new csv.CommonCSV('conf/insurgency_team.dat', ['Id']);
    global.gConfInsurgencyAward = new csv.CommonCSV('conf/insurgency_award.dat', ['Id']);
    for (var id in gConfInsurgencyTeam) {
        checkBattleMonsterConf(gConfInsurgencyTeam[id], util.format('insurgency_team.dat Id=%d', id));
    }

    global.gConfAssistMineTeam = new csv.CommonCSV('conf/assist_mine_team.dat', ['Id']);
    global.gConfAssistMineAward = new csv.CommonCSV('conf/assist_mine_award.dat', ['Id']);
    for (var id in gConfAssistMineTeam) {
        checkBattleMonsterConf(gConfAssistMineTeam[id], util.format('assist_mine_team.dat Id=%d', id));
    }

    // 日积月累
    global.gConfDayMonthPayAward = new csv.CommonCSV('conf/daymonthpay_reward.dat', ['ConfId', 'Id']);

    // 夺宝之旅
    global.gConfTreasureTravel = new csv.CommonCSV('conf/treasuretravel.dat', ['ConfId', 'Pos']);
    global.gConfTreasureTravelItem = new csv.CommonCSV('conf/treasuretravel_item.dat', ['Id']);
    global.gConfTreasureTravelLevel = new csv.CommonCSV('conf/treasuretravel_level.dat', ['ConfId', 'Level']);

    // 新春签到
    global.gConfNewYearSign = new csv.CommonCSV('conf/newyearsign.dat', ['ConfId', 'Day']);
    objectForEach(gConfNewYearSign, function(confId, confs) {
        var maxDay = 1;
        objectForEachKey(confs, function(day) {
            maxDay = Math.max(maxDay, +day);
        });
        confs[0].MaxDay = maxDay;
    });

    // 英雄志
    global.gConfHeroLog = new csv.HeroLogCSV('conf/herolog.dat', ['Id', 'Checkpoint', 'Level']);
    global.gConfHeroLogPlacement = new csv.HeroLogPlacementCSV('conf/herolog_placement.dat', ['Id']);
    global.gConfHeroLogChapterAward = new csv.CommonCSV('conf/herolog_chapter_award.dat', ['Chapter']);
    for (var chapter in gConfHeroLog) {
        for (var checkpoint in gConfHeroLog[chapter]) {
            for (var level in gConfHeroLog[chapter][checkpoint]) {
                checkBattleMonsterConf(gConfHeroLog[chapter][checkpoint][level], util.format('herolog_team.dat chapter=%d checkpoint=%d level=%d', chapter, checkpoint, level));
            }
        }
    }

    // 星座奇缘
    if (gConfSwitch.xingzuoRomance) {
        global.gConfXingzuoRomance = new csv.CommonCSV('conf/xingzuo_romance.dat', ['Id']);
        global.gConfXingzuoRomanceShop = new csv.CommonCSV('conf/xingzuo_romance_shop.dat', ['Id']);
    }

    // 星魂农场
    if (gConfSwitch.HoroscopeFarm) {
        global.gConfHoroscopeLand = new csv.CommonCSV('conf/horoscopefarm_land.dat', ['Id']);
        global.gConfHoroscopeSeed = new csv.CommonCSV('conf/horoscopefarm_seed.dat', ['Id']);
        global.gConfHoroscopeExchange = new csv.CommonCSV('conf/horoscopefarm_exchange.dat', ['Id']);
    }
    global.gConfHoroscopeFarmTreeAward = new csv.CommonCSV('conf/horoscorpefarm_tree_awards_assistor.dat', ['Id']);

    // QQ电脑管家推广
    global.gConfQQPCManager = new csv.CommonCSV('conf/qqpcmgr.dat', ['Id']);

    loadConfRuntime();
}

function loadConfRuntime() {
    global.gConfRuntime = {};

    /*
     *战术大赛
     */
    gConfRuntime.TroopMatchStartTime = (new Date('2013-12-16 00:00:00')).getStamp();
    
    /*
     *军团科技
     */
    gConfRuntime.LeagueTechMaxLevel = 0;
    for (var level in gConfLeagueTech[1]) {
        gConfRuntime.LeagueTechMaxLevel = Math.max(gConfRuntime.LeagueTechMaxLevel, +level);
    }

    /*
     *九州英雄榜
     */
    var zeroTime = new Date('1970-01-01 00:00:00');
    var relativeSeconds = (gConfGlobal.SmashLandRankOpenWeekDay - zeroTime.getDay()) * 86400;
    gConfRuntime.SmashLandRankFirstOpenTime = zeroTime.getStamp() + relativeSeconds;

    /*
     *新成就系统
     */
    gConfRuntime.AchievementEventMap = {};
    for (var id in gConfAchieveGoal) {
        var goalEvent = gConfAchieveGoal[id][1].GoalEvent;
        var eventAchievements = gConfRuntime.AchievementEventMap[goalEvent];
        if (!eventAchievements) {
            eventAchievements = {};
            gConfRuntime.AchievementEventMap[goalEvent] = eventAchievements;
        }
        eventAchievements[id] = 1;
    }
    
    /*
     *充值幸运转
     */
    gConfRuntime.LuckyChargePosWeights = {};
    for (var confId in gConfAvLuckyCharge) {
        var conf = gConfAvLuckyCharge[confId];
        var confItems = gConfAvLuckyChargeItem[confId];
        var posWeights = {};
        for (var pos in conf) {
            posWeights[pos] = conf[pos].Weight;

            var items = conf[pos].Item.split("|");
            var itemWeights = {};
            var existCard = false;
            items.forEach(function(item) {
                var itemConf = confItems[item]; 
                itemWeights[item] = itemConf.Weight;
                if (itemConf.Award1 && itemConf.Award1[0] == 'card') {
                    existCard = true;
                }
            });
            conf[pos].ItemWeights = itemWeights;
            conf[pos].ExistCard = existCard;
        }
        gConfRuntime.LuckyChargePosWeights[confId] = posWeights;
    }

    gConfRuntime.LuckyChargeTimesMax = 0;
    for (var times in gConfAvLuckyChargeCost) {
        gConfRuntime.LuckyChargeTimesMax = Math.max(gConfRuntime.LuckyChargeTimesMax, times);
    }

    gConfRuntime.LuckyChargeRankThrowMin = {};
    gConfRuntime.LuckyChargeRankMax = {};
    for (var confId in gConfAvLuckyChargeRank) {
        var confs = gConfAvLuckyChargeRank[confId];
        var throwMin = Number.MAX_VALUE;
        var rankMax = 0;
        for (var id in confs) {
            throwMin = Math.min(confs[id].ThrowMin, throwMin);
            rankMax = Math.max(confs[id].Rank, rankMax);
        }
        gConfRuntime.LuckyChargeRankThrowMin[confId] = throwMin;
        gConfRuntime.LuckyChargeRankMax[confId] = rankMax;
    }

    /*
     *地牢
     */
    gConfRuntime.PrisonAwardWeights = {};
    for (var id in gConfPrisonAward) {
        gConfRuntime.PrisonAwardWeights[id] = gConfPrisonAward[id].Weight;
    }

    /*
     *御前科举
     */
    gConfRuntime.ImperialExaminationQuestionCount = Object.keys(gConfImperialExaminationQA).length;

    /*
     *王者战场
     */
    gConfRuntime.champsbattle = {
        PeriodSeconds: 0,       //每周期秒数
        StartSeconds: 0,        //正式开始时间距离本周期开始时间的秒数
        StepRegister: 0,        //玩家报名的阶段Id
        StepWaiting: 0,         //等待开启的阶段Id
        StepFinal: 0,           //总决赛的阶段Id

        stepFields: {},         //每阶段的战场列表
        mainCitys: {},          //各阵营的主城Id
        battleCitys: {},        //各阵营的战场城池列表
        teamIndexs: {},         //NPC部队索引{$day:[teamId]}
        Code: {
            kSuccess: 0,
            kNotEnterable: 1,		//没资格进入战场
            kNotRegister: 2,		//本服未报名
            kFrequently: 3,			//访问太频繁
            kScheduleTimeout: 4,	//当前阶段已结束
            kTeamLocking: 5,		//部队锁定中
            kTeamDead: 6,			//部队已阵亡
            kTeamNotInField: 7,		//部队不在战场中
            kCityArmyFull: 101,		//城池部队已满
            kCityExistEnemy: 102,	//当前城池还存在敌人
            kNoReliveTimes: 201,	//没有复活次数
        },

        Camp: {
            kMid: 0,     //中立
            kShu: 1,     //吴蜀
            kWei: 2,     //北魏
        },

        City: {
            kMain: 0,        //主城
            kResource: 1,    //资源点
            kBattle: 2,      //战斗点
        },
        
        Action: {
        	kNone: 0,
        	kFight: 1,
        	kMove: 2,
        },

        load: function() {
            var Camp = this.Camp;
            var City = this.City;
            var teamIndexs = this.teamIndexs;

            for (var step in gConfChampsBattleSchedule) {
                var stepConf = gConfChampsBattleSchedule[step];
                stepConf.StartSeconds = stepConf.StartDay*86400 + stepConf.StartHour*3600;
                stepConf.EndSeconds = stepConf.StartSeconds + stepConf.KeepHour*3600;

                if (0 == stepConf.Group) {
                    this.StepRegister = +step;
                } else if (1 == stepConf.Group) {
                    this.StepFinal = +step;
                }

                this.stepFields[+step] = [];
            }

            this.PeriodSeconds = gConfGlobal.ChampsBattlePeriodDays*86400;
            this.StartSeconds = gConfChampsBattleSchedule[1].StartSeconds;

            for (var id in gConfChampsBattleField) {
                var step = +gConfChampsBattleField[id].Step;
                this.stepFields[step].push(+id);
            }

            this.battleCitys[Camp.kMid] = [];
            this.battleCitys[Camp.kShu] = [];
            this.battleCitys[Camp.kWei] = [];

            for (var id in gConfChampsBattleFieldCity) {
                var city = gConfChampsBattleFieldCity[id];
                if (City.kMain == city.Type) {
                    this.mainCitys[city.Camp] = +id;
                } else if (City.kBattle == city.Type) {
                    this.battleCitys[city.Camp].push(+id);
                }
                city.OpenSeconds = city.OpenTime*60;
            }

            for (var t in gConfChampsBattleRelive) {
            	gConfChampsBattleRelive[t].TimeSeconds = t*60;
            }

            objectForEach(gConfChampsBattleTeam, function(id, item) {
                var indexs = teamIndexs[item.Day];
                if (!indexs) {
                    indexs = [];
                    teamIndexs[item.Day] = indexs;
                }
                indexs.push(+id);
            });
        },

        getRoundSeconds: function() {
            return (Date.getStamp() - gConfGlobal.ChampsBattleFirstOpenTime) % this.PeriodSeconds;
        },

        getRound: function() {
            return Math.ceil((Date.getStamp() - gConfGlobal.ChampsBattleFirstOpenTime) / this.PeriodSeconds);
        },

        getSchedule: function() {
            var seconds = this.getRoundSeconds();
            var schedule = {step:this.StepWaiting, keep:false};

            for (var step in gConfChampsBattleSchedule) {
                var stepConf = gConfChampsBattleSchedule[step];
                if (seconds < stepConf.StartSeconds) {
                    break;
                }
                schedule.step = +step;
                schedule.keep = (seconds < stepConf.EndSeconds);
            }

            return schedule;
        },

        getNextSchedule: function(schedule) {
            var nextSchedule = clone(schedule);
            if (nextSchedule.keep) {
                nextSchedule.keep = false;
            } else {
                nextSchedule.keep = true;
                nextSchedule.step++;
                if (!gConfChampsBattleSchedule[nextSchedule.step]) {
                    nextSchedule.step = this.StepWaiting;
                    nextSchedule.keep = false;
                }
            }
            return nextSchedule;
        },
        
        isFightingSchedule: function(schedule) {
        	return (schedule.keep && (schedule.step > this.StepRegister));
        },
        
        getEnemyCamp: function(camp) {
        	return (this.Camp.kShu == camp) ? this.Camp.kWei :this.Camp.kShu;
        }
    }

    gConfRuntime.champsbattle.load();


    /*
     *决战天下
     */
    gConfRuntime.battleWorld = {
        PeriodSeconds: 0,       //每周期秒数
        StartSeconds: 0,        //正式开始时间距离本周期开始时间的秒数
        StepWaiting: 'waiting', //等待开启的阶段Id
        StepRegister: 'register',
        StepSequence: ['register', 9, 3, 1], //阶段序列

        load: function() {
            for (var step in gConfBattleWorldSchedule) {
                var stepConf = gConfBattleWorldSchedule[step];
                stepConf.StartSeconds = Math.floor((parseInt(stepConf.StartWeek)%7)*86400 + stepConf.StartTime*3600);
                stepConf.EndSeconds = Math.floor(stepConf.StartSeconds + stepConf.KeepHour*3600);
            }
            
            var steps = this.StepSequence; 
            for (var i = 0, len = steps.length; i < len; ++i) {
                var stepConf = gConfBattleWorldSchedule[steps[i]];
                if (i + 1 < len) {
                    stepConf.Next = steps[i + 1];
                } else {
                    stepConf.Next = this.StepWaiting; 
                }
            }

            this.PeriodSeconds = gConfGlobal.BattleWorldPeriodDays*86400;
            this.StartSeconds = gConfBattleWorldSchedule[this.StepRegister].StartSeconds;
        },

        getRoundSeconds: function() {
            return (Date.getStamp() - gConfGlobal.BattleWorldFirstOpenTime) % this.PeriodSeconds;
        },

        getRound: function() {
            return Math.ceil((Date.getStamp() - gConfGlobal.BattleWorldFirstOpenTime) / (gConfGlobal.BattleWorldKeepDays*86400));
        },

        getSchedule: function() {
            var seconds = this.getRoundSeconds();
            var schedule = {step:this.StepWaiting, keep:false};

            if (seconds > gConfGlobal.BattleWorldKeepDays*86400) {
                return schedule;
            }
            
            
            var steps = this.StepSequence;
            for (var i = 0, len = steps.length; i < len; ++i) {
                var stepConf = gConfBattleWorldSchedule[steps[i]];
                if (seconds < stepConf.StartSeconds) {
                    break;
                }

                schedule.step = steps[i];
                schedule.keep = (seconds < stepConf.EndSeconds);
            }

            return schedule;
        },

        getNextSchedule: function(schedule) {
            var nextSchedule = clone(schedule);
            if (nextSchedule.keep) {
                nextSchedule.keep = false;
            } else {
                nextSchedule.keep = true;
                if (this.StepWaiting == schedule.step) {
                    nextSchedule.step = this.StepRegister;
                } else {
                    nextSchedule.step = gConfBattleWorldSchedule[schedule.step].Next;
                    if (this.StepWaiting == nextSchedule.step) {
                        nextSchedule.keep = false;
                    }
                }
            }
            return nextSchedule;
        },
        
        isFightingSchedule: function(schedule) {
        	return (schedule.keep && !isNaN(schedule.step));
        },
    }

    gConfRuntime.battleWorld.load();


    /*
     *武将升星
     */
    gConfRuntime.RoleStarRestrainAttrs = {}; //{$soldierKind:{$starLevel:attrs}}
    objectForEach(gConfRoleStar, function(soldierKind, starLevelsConf) {
        var starRestrainAttrs = {};
        objectForEach(starLevelsConf, function(starLevel, starConf) {
            var restrainAttrs = {};
            for (var i = 1; i <= 3; ++i) {
                var specialEffectId = starConf['SpecialEffect'+i];
                if (specialEffectId) {
                    var specialEffectConf = gConfRoleStarSpecialEffect[soldierKind][specialEffectId];
                    for (var kind = 1; kind <= 5; ++kind) {
                        var restrainKind = 'Restrain'+kind;
                        var restrainValue = +specialEffectConf[restrainKind];
                        if (restrainValue) {
                            addAttrValue(restrainAttrs, restrainKind, restrainValue);
                        }
                    }

                    var restrainKind = 'RestrainSplash';
                    var restrainValue = +specialEffectConf[restrainKind];
                    if (restrainValue) {
                        addAttrValue(restrainAttrs, restrainKind, restrainValue);
                    }
                }
            }
            starRestrainAttrs[starLevel] = restrainAttrs;
        });
        gConfRuntime.RoleStarRestrainAttrs[soldierKind] = starRestrainAttrs;
    });

    /**
     *夺宝之旅
     */
    gConfRuntime.TreasureTravelPosMax = 1;
    objectForEach(gConfTreasureTravel, function(confId, confs) {
        objectForEachKey(confs, function(pos) {
            gConfRuntime.TreasureTravelPosMax = Math.max(gConfRuntime.TreasureTravelPosMax, +pos);
        });

        objectForEach(confs, function(pos, conf) {
            //位置权重
            var posWeights = {};
            for (var i = 0; i < 6; ++i) {
                var tempPos = ((+pos) + i - 1) % gConfRuntime.TreasureTravelPosMax + 1;
                posWeights[tempPos] = confs[tempPos].Weight;
            }
            conf.PosWeights = posWeights;

            //物品权重
            if (typeof conf.Item == "string") {
                // 免费物品
                var itemWeights = {};
                var items = conf.Item.split("|");
                items.forEach(function(item) {
                    var itemConf = gConfTreasureTravelItem[item];
                    itemWeights[item] = itemConf.Weight;
                });
                conf.ItemWeights = itemWeights;
            }
            
            if (typeof conf.ItemPay == "string") {
                // 付费物品
                var payItemWeights = {};
                var payItems = conf.ItemPay.split("|");
                payItems.forEach(function(item) {
                    var itemConf = gConfTreasureTravelItem[item];
                    payItemWeights[item] = itemConf.Weight;
                });
                conf.PayItemWeights = payItemWeights;
            }
        });
    });
    gConfRuntime.TreasureTravelBuyMaxCost = 0;
    for (var i = 1; ; ++i) {
        var confBuy = gConfBuy[i];
        if (!confBuy || !confBuy.TreasureTravel) break;
        gConfRuntime.TreasureTravelBuyMaxCost = +confBuy.TreasureTravel;
    }

    // 星魂农场
    if (gConfSwitch.HoroscopeFarm) {
        var horoscopeFarmSeedWeights = {};
        objectForEach(gConfHoroscopeSeed, function(id, seed) {
            horoscopeFarmSeedWeights[id] = seed.Weight;
        });
        gConfRuntime.HoroscopeFarmSeedWeights = horoscopeFarmSeedWeights;
        gConfRuntime.HoroscopeFarmStoreSeedCount = 9;
    }
    
    // 仙灵树被协助的最大次数
    gConfRuntime.HoroscopeFarmTreeAssistTimes = 2;
}

function loadDB(callback, poolSize) {
    poolSize = poolSize || 2;

    var mongoServer = null;
    if( config.MongodbSets ) {
        var servers = [];
        config.MongodbSets.forEach(function(serverConf){
            servers.push(new mongodb.Server(serverConf[0], serverConf[1],
                        {auto_reconnect:true, poolSize:poolSize}));
        });
        mongoServer = new mongodb.ReplSetServers(servers);
    }else{
        mongoServer = new mongodb.Server(config.MongodbHost, config.MongodbPort,
                        {auto_reconnect:true, poolSize:poolSize});
    }

    var db = new mongodb.Db(config.MongodbName, mongoServer, 
                    {'native_parser':true, 'w':1, 'wtimeout':10, 'fsync':false});
    db.open(function(err, db) {
        if( err ) {
            ERROR(err);
            process.exit(-1);
        }

        callback && callback(db);
    });
}

function loadCache(callback) {
    var client = redis.createClient(config.RedisPort, config.RedisHost);
    client.select(config.RedisId, function(err){
        if( err ) {
            ERROR(err);
            process.exit(-1);
        }
    });

    client.on('ready', function(){
        callback && callback(client);
    });

    client.on('error', function(e){
        ERROR(e);
    });
}

function getHttpClientIP(req) {
    return req.headers['x-forwarded-for'] ||
        req.connection.remoteAddress ||
        req.socket.remoteAddress || "unknown";
}

// 创建web服务器
function startWebServer(serverName, port, ip, handler, onExit) {
    var isExiting = false;
    var httpHandler = function(req, res) {
        if( isExiting ) {
            req.connection.destroy();
            return;
        }

        var chunks = [];
        var received = 0;
        req.on('data', function(chunk) {
            chunks.push(chunk);
            received += chunk.length;
            // POST请求不能超过100K
            if( received > 102400 ) {
                req.connection.destroy();
                return;
            }
        });

        req.on('end', function() {
            if( req.url == '/crossdomain.xml') {
                res.writeHead(200, common.defaultHeaders);
                res.end(common.defaultCrossDomain);
                return;
            }

            var rawData = '';
            if( req.method == 'POST' ) {
                rawData = Buffer.concat(chunks, received).toString();
            }else{
                rawData = url.parse(req.url).query;
            }

            query = qs.parse(rawData);
            res._query = query;
            res._time = +(new Date());
            //res._compress = req.headers['accept-encoding'] || '';
            
            query.clientIP = getHttpClientIP(req);
            handleReq(query, res, handler);
        });
    };

    var pidFile = serverName + '.pid';
    process.on('SIGINT', beforExit);
    process.on('SIGTERM', beforExit);

    process.on('uncaughtException', function (err) {
        ERROR(err.stack);
    });

    function beforExit() {
        if( isExiting ) return;
        INFO(serverName + ' begin shutdown');
        isExiting = true;

        if( onExit ) {
            onExit(endExit);
        }else{
            endExit();
        }
    }

    function endExit() {
        fs.existsSync(pidFile) && fs.unlinkSync(pidFile);
        INFO(serverName + ' end shutdown');
        process.exit();
    }

    var server = http.createServer(httpHandler);
    server.listen(port, ip, function(){
        INFO(serverName + ' start');
        fs.writeFileSync(pidFile, process.pid, 'utf8');
    });
    server.on('error', function(e){
        if (e.code == 'EADDRINUSE') {
            ERROR(e);
            process.exit(-1);
        } else {
            ERROR(e);
        }
    })

    if( config.HttpsKey && config.HttpsCrt ) {
        var options = {
            key: fs.readFileSync(config.HttpsKey, 'utf8'),
            cert: fs.readFileSync(config.HttpsCrt, 'utf8')
        };
        var sserver = https.createServer(options, httpHandler);
        sserver.listen(port+1000, ip);
    }

    return server;
}

function handleReq(query, res, handler) {
    var code = 1;
    var desc = '';

    query.uid = +query.uid;
    if( !query.mod ) {
        desc = 'no mod';    
    }else if( !query.act ) {
        desc = 'no act';
    }else if( !query.uid ) {
        desc = 'no uid';
    }else if( !query.args ) {
        desc = 'no args';
    }else{
        try{
            query.args = JSON.parse(query.args); 
            code = 0;
        }catch(error){
            ERROR('JSON: ' + query.uid + ' ' + query.args);
            desc = 'args not in json format';
        }
    }

    var resp = {
        'code': code, 
        'desc': desc, 
        'mod': query.mod, 
        'act': query.act, 
        'args': query.args,
        'data': {}
    };

    if( resp.code != 0 ) {
        onReqHandled(res, resp);
        return;
    }
    handler(query, res, resp);
}

global.onReqHandled = function(res, data, isCompress) {
    if( !data.hasOwnProperty('code') ) {
        data.code = 1;
        data.desc = 'no code';
    }

    if( !data.hasOwnProperty('desc') ) {
        data.desc = '';
    }

    data.serverTime = common.getTime();
    var strData = JSON.stringify(data)
    
    if( isCompress && !config.NotGzip && strData.length > 1024 ) {
        zlib.gzip(strData, function(err, buf){
            res.writeHead(200, common.gzipHeaders);
            res.end(buf);
        });
    }else{
        res.writeHead(200, common.defaultHeaders);
        res.end(strData);
    }
    
    var timeCost = +(new Date()) - res._time;
    var query = res._query;

    if (data.nolog != 1) {
        LOG(util.format('%s %s %s %s %j %d %d %s', query.uid, query.mod, query.act, 
            query.seq||0, query.args, timeCost, data.code, data.desc));
    }
}

global.reportQQ = function(action, args, pf){
    if( !config.Pay ) return;

    /*
    QQ空间为1；
    腾讯朋友为2；
    腾讯微博为3；
    Q+平台为4；
    手机QQ空间为8；
    手机腾讯朋友为9；
    QQGame为10；
    3366为11；
    QQGame官网为12；
    漫游为15；
    游戏人生为16；
    游戏联盟为17 
    */
    var domain = 1;
    if( pf == 'pengyou' ) {
        domain = 2;
    }else if( pf == '3366' ) {
        domain = 11;
    }

    args['appid'] = '100712667';
    args['userip'] = 1245633332;
    args['svrip'] = 1434394239;
    args['time'] = common.getTime();
    args['domain'] = domain;
    args['worldid'] = config.ServerId;
    args['opopenid'] = args['opuid'];

    var strArgs = qs.stringify(args);
    http.get(util.format("http://tencentlog.com/stat/report_%s.php?%s", action, strArgs));
}

exports.loadDB = loadDB;
exports.loadCache = loadCache;
exports.loadConf = loadConf;
exports.startWebServer = startWebServer;
exports.loadGlobalServerConf = loadGlobalServerConf;
